//
//  NetworkTools.swift
//  MyWeibo
//
//  Created by 余丽丽 on 15/10/10.
//  Copyright © 2015年 余丽丽. All rights reserved.
//

import UIKit
import AFNetworking
// HTTP请求方法枚举
enum RequestMethod:String{
    case GET = "GET"
    case POST = "POST"
}

// MARK: - 封装错误消息:
/// 错误的类别标记
private let YLLErrorDomainName = "com.yuliliWeibo.error.network"
/// 网络访问错误信息 - 枚举，是定义一组类似的值
/// Swift 中枚举可以定义函数和属性，跟`类`有点像
private enum YLLNetworkError: Int{
    case emptyDataError = -1
    case emptyTokenError = -2
    
    /// 错误描述
    private var errorDescription: String{
    
        switch self{
            case .emptyDataError: return "Error:数据为空!!!"
            case .emptyTokenError: return "Error:Token不存在或者失效!!!"
        }
    
    }
    
    private func error() -> NSError{
    
        return NSError(domain: YLLErrorDomainName, code: rawValue, userInfo: [YLLErrorDomainName: errorDescription])
    }
 
}

// MARK: - class NetworkTools
class NetworkTools: AFHTTPSessionManager {

    // 单例
    static let sharedTools:NetworkTools = {
    
        let baseURL = NSURL(string: "https://api.weibo.com/")
        let tools = NetworkTools(baseURL: baseURL)
        //设置数据解析格式
        tools.responseSerializer.acceptableContentTypes = NSSet(objects: "application/json", "text/json", "text/javascript", "text/plain") as Set<NSObject>
        
        return tools
    
    }()
    
    // **************************** 准备OAuth授权数据 ****************************
    // MARK: OAuth授权
    /*
            您于2015/10/10在微博开放平台创建了应用“誓爱仿微博”，请妥善保管以下应用信息，以免泄露被他人利用：
            App key：1207411905
            App secret：e1563aabe29a4305f9b4d70c282f9ea1
    */
    private let clientId = "1207411905"
    private let appSecret = "e1563aabe29a4305f9b4d70c282f9ea1"
    /// 回调地址
    let redireUri = "https://git.oschina.net/HMLL/MyWeibo"
    
    // **************************** 返回OAuth的授权地址 ****************************
    // MARK: 返回授权请求登录URL:
    /*
            请求:https://api.weibo.com/oauth2/authorize?client_id=123050457758183&redirect_uri=http://www.example.com/response&response_type=code
            同意授权后会重定向:http://www.example.com/response&code=CODE
    */
    func oauthUrl()->NSURL{
        //拼接字符串
        let urlString = "https://api.weibo.com/oauth2/authorize?client_id=\(clientId)&redirect_uri=\(redireUri)"
        return NSURL(string: urlString)!
    }
    
    // **************************** 根据code加载Token ****************************
    // MARK: 根据code加载Token:
    /*
            url:https://api.weibo.com/oauth2/access_token
            POST
            请求参数:
            client_id       true	string	申请应用时分配的AppKey。
            client_secret	true	string	申请应用时分配的AppSecret。
            grant_type      true	string	请求的类型，填写authorization_code
            grant_type为authorization_code时
            必选	类型及范围	说明
            code            true	string	调用authorize获得的code值。
            redirect_uri	true	string	回调地址，需需与注册应用里的回调地址一致。
            返回数据:
            {
            "access_token": "ACCESS_TOKEN",
            "expires_in": 1234,
            "remind_in":"798114",
            "uid":"12341234"
            }
            返回值字段       字段类型	字段说明
            access_token	string	用于调用access_token，接口获取授权后的access token。
            expires_in	    string	access_token的生命周期，单位是秒数。
            remind_in	    string	access_token的生命周期（该参数即将废弃，开发者请使用expires_in）。
            uid             string	当前授权用户的UID。
    */
    func loadAccessToken(code : String,finished:RequestFinishedCallBack){
    
        let urlString = "https://api.weibo.com/oauth2/access_token"
        //字典
        let params = ["client_id": clientId,
            "client_secret": appSecret,
            "grant_type": "authorization_code",
            "code": code,
            "redirect_uri": redireUri]
        
        request(.POST, urlString: urlString, parameters: params, finished: finished)
//        POST(urlString, parameters: params, success: { (_, JSON) -> Void in
//            // 成功
//            finished(result: JSON as? [String : AnyObject], error: nil)
//            }) { (_, error) -> Void in
//                print(error)
//                finished(result: nil, error: error)
//        }
         /* 测试代码
                //1. 设置响应数据格式为二进制数据 AFN 不会做 JSON 反序列化
                responseSerializer = AFHTTPResponseSerializer()
        
                //2. 测试网络代码 － Swift 开发中，凡是碰到 AnyObject 要想使用，就必须转换！
                request(.POST, urlString: "https://api.weibo.com/oauth2/access_token", parameters: params) { (result, error) -> () in
                // result 是一个 NSData
                // 将数据转换成 NSString
                let string = NSString(data: result as! NSData, encoding: NSUTF8StringEncoding)
        
                // {"access_token":"2.00ml8IrFKlq63E7ccdbba6c5OotBTD","remind_in":"157679999","expires_in":157679999,"uid":"5365823342"}
                // 提示：JSON 反序列化的时候，如果数字没有引号，转换成 NSNumber，可能会导致 KVC 的崩溃！
                print(string)
                }
        */
    }
    
    // **************************** 检测Token ****************************
    // MARK: 判断token是否存在或者过期
    private func checkToken(finished:RequestFinishedCallBack) -> [String: AnyObject]?{
    
        // 判断token是否存在或者过期
        if UserAccount.loadAccount()?.access_token == nil {
            printError(YLLNetworkError.emptyTokenError.error())
            return nil
        }
    
        //返回Tonken字典
        return ["access_token": UserAccount.loadAccount()!.access_token!]
    }
  
    
    // **************************** 根据Token加载用户数据 ****************************
    // MARK: 根据Token加载用户数据:
    /*
    
            HTTP请求方式:GET
            URL:https://api.weibo.com/2/users/show.json
            返回结果支持格式:JSON
            是否需要登录:是
            请求参数          必选    类型及范围       说明
            source          false	string      采用OAuth授权方式不需要此参数，其他授权方式为必填参数，数值为应用的AppKey。
            access_token	false	string      采用OAuth授权方式为必填参数，其他授权方式不需要此参数，OAuth授权后获得。
            uid	false       int64               需要查询的用户ID。
            screen_name     false	string      需要查询的用户昵称。
            备注:uid与screen_name二者必选其一，且只能选其一
    */
    func loadUserInfo(uid:String,finished:RequestFinishedCallBack){
     
        //获取用户信息
        // guard 不仅可以用 let，而且可以用 var
        guard var params: [String: AnyObject] = checkToken(finished) else{
            return
        }
        params["uid"] = uid
        let urlString = "https://api.weibo.com/2/users/show.json"
        request(.GET, urlString:urlString , parameters: params, finished: finished)
    
    }
    
    
    // **************************** 加载微博数据 ****************************
   
    // MARK: - 加载所关注用户的最新微博数据:
    /*
            API文档:http://open.weibo.com/wiki/2/statuses/home_timeline
            HTTP请求方式:GET
            URL:https://api.weibo.com/2/statuses/home_timeline.json
            返回结果支持格式:JSON
            是否需要登录:是
            请求参数          必选    类型及范围	说明
            source          false	string      采用OAuth授权方式不需要此参数，其他授权方式为必填参数，数值为应用的AppKey。
            access_token	false	string      采用OAuth授权方式为必填参数，其他授权方式不需要此参数，OAuth授权后获得。
            since_id        false	int64       若指定此参数，则返回ID比since_id大的微博（即比since_id时间晚的微博），默认为0。
            max_id          false	int64       若指定此参数，则返回ID小于或等于max_id的微博，默认为0。
            count           false	int         单页返回的记录条数，最大不超过100，默认为20。
            page            false	int         返回结果的页码，默认为1。
            base_app        false	int         是否只获取当前应用的数据。0为否（所有数据），1为是（仅当前应用），默认为0。
            feature         false	int         过滤类型ID，0：全部、1：原创、2：图片、3：视频、4：音乐，默认为0。
            trim_user       false	int         返回值中user字段开关，0：返回完整user字段、1：user字段仅返回user_id，默认为0。
        */
    
    func loadStatus(finished:RequestFinishedCallBack){
        // 定义参数
        guard var params = checkToken(finished) else{
            return
        }
        
        if since_id > 0 {
            params["since_id"] = since_id
        }
        if max_id > 0 {
            params["max_id"] = max_id - 1
        }
        
        print(params)
        //定义请求URL
        let urlString = "https://api.weibo.com/2/statuses/home_timeline.json"
        
        //发送请求
        request(RequestMethod.GET, urlString: urlString, parameters: params, finished: finished)
        
    }
    
    
    
    // **************************** 封装 AFN 网络方法 ****************************
    // MARK: - 封装 AFN 网络访问方法
    // : 网络请求完成回调的数据类型:
    // Swift 开发中，凡是碰到 AnyObject 要想使用，就必须转换！
    typealias RequestFinishedCallBack = (result:AnyObject?,error:NSError?)->()
    // : 封装 AFN 网络请求方法:
    private func request(method:RequestMethod, urlString: String, parameters: [String: AnyObject]?, finished: RequestFinishedCallBack){
    
        //闭包是提前准备好代码,可以当做参数传递
        //success: ((NSURLSessionDataTask, AnyObject) -> Void)?
        let success = {(task: NSURLSessionDataTask,result:AnyObject) -> () in
            finished(result: result, error: nil)
        }
        
        //failure: ((NSURLSessionDataTask, NSError) -> Void)?) -> NSURLSessionDataTask?
        let failure = {(task: NSURLSessionDataTask, error: NSError) -> () in
            finished(result: nil, error: error)
        }
        
        if method == RequestMethod.GET {
            GET(urlString, parameters: parameters, success: success, failure: failure)
        }else{
            POST(urlString, parameters: parameters, success: success, failure: failure)
        }
        
    }
    
    // MARK: 打印错误信息
    private func printError(error: NSError){
        print(error)
    }
}
